﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace LPBToolsLib
{
    /// <summary>
    /// 安全加密工具
    /// </summary>
    public class SecurityTools
    {
        public static string MD5(string str)
        {
            MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
            byte[] bytValue, bytHash;
            bytValue = System.Text.Encoding.UTF8.GetBytes(str);
            bytHash = md5.ComputeHash(bytValue);
            md5.Clear();
            string sTemp = "";
            for (int i = 0; i < bytHash.Length; i++)
            {
                sTemp += bytHash[i].ToString("X").PadLeft(2, '0');
            }
            str = sTemp.ToLower();
            return str;
        }
        /// <summary>        
        /// 计算文件的MD5校验        
        /// </summary>        
        /// <param name="fileName"></param>        
        /// <returns></returns>        
        public static string GetMD5HashFromFile(string fileName)
        {
            if (File.Exists(fileName))
            {
                FileStream file = new FileStream(fileName, FileMode.Open);
                MD5 md5 = new MD5CryptoServiceProvider();
                byte[] retVal = md5.ComputeHash(file);
                file.Close();
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < retVal.Length; i++)
                {
                    sb.Append(retVal[i].ToString("x2"));
                }
                return sb.ToString();
            }
            else
                return "";
        }

        public static string GetMD5StringUTF8(string str)
        {
            byte[] result = Encoding.UTF8.GetBytes(str.Trim());    //输入密码的文本
            MD5 md5 = new MD5CryptoServiceProvider();
            byte[] output = md5.ComputeHash(result);
            return BitConverter.ToString(output).Replace("-", "").ToUpper();    //输出加密文本
        }

        protected static bool AESEncrypt(ref MemoryStream sourData, String Key, String Vector)
        {
            Byte[] bKey = new Byte[32];
            Array.Copy(Encoding.UTF8.GetBytes(Key.PadRight(bKey.Length)), bKey, bKey.Length);
            Byte[] bVector = new Byte[16];
            Array.Copy(Encoding.UTF8.GetBytes(Vector.PadRight(bVector.Length)), bVector, bVector.Length);
            Rijndael Aes = Rijndael.Create();
            Byte[] plainBytes = sourData.ToArray();
            if (plainBytes.Length > 0)
            {
                sourData.Seek(0, SeekOrigin.Begin);
                sourData.SetLength(0);
                // 把内存流对象包装成加密流对象
                CryptoStream Encryptor = new CryptoStream(sourData, Aes.CreateEncryptor(bKey, bVector), CryptoStreamMode.Write);
                // 明文数据写入加密流
                Encryptor.Write(plainBytes, 0, plainBytes.Length);
                Encryptor.FlushFinalBlock();
                return true;
            }
            else
                return false;
        }
        protected static bool AESDecrypt(ref MemoryStream sourData, String Key, String Vector)
        {
            MemoryStream fAesMemory = new MemoryStream();
            Byte[] bKey = new Byte[32];
            Array.Copy(Encoding.UTF8.GetBytes(Key.PadRight(bKey.Length)), bKey, bKey.Length);
            Byte[] bVector = new Byte[16];
            Array.Copy(Encoding.UTF8.GetBytes(Vector.PadRight(bVector.Length)), bVector, bVector.Length);
            Rijndael Aes = Rijndael.Create();
            Byte[] plainBytes = sourData.ToArray();
            // 把内存流对象包装成加密流对象
            CryptoStream Decryptor = new CryptoStream(sourData, Aes.CreateDecryptor(bKey, bVector), CryptoStreamMode.Read);
            Byte[] Buffer = new Byte[1024];
            Int32 readBytes = 0;
            while ((readBytes = Decryptor.Read(Buffer, 0, Buffer.Length)) > 0)
            {
                fAesMemory.Write(Buffer, 0, readBytes);
            }
            sourData = fAesMemory;
            return true;
        }

        /// <summary>
        /// AES加密
        /// </summary>
        /// <param name="Data">被加密的明文</param>
        /// <param name="Key">密钥</param>
        /// <param name="Vector">向量</param>
        /// <returns>密文</returns>
        public static String AESEncrypt(String Data, String Key, String Vector)
        {
            Byte[] plainBytes = Encoding.UTF8.GetBytes(Data);
            Byte[] Cryptograph = null; // 加密后的密文            
            MemoryStream Memoryx = new MemoryStream();
            Memoryx.Write(plainBytes, 0, plainBytes.Length);
            if (AESEncrypt(ref Memoryx, Key, Vector))
                Cryptograph = Memoryx.ToArray();
            return Convert.ToBase64String(Cryptograph);
        }

        /// <summary>
        /// AES解密
        /// </summary>
        /// <param name="Data">被解密的密文</param>
        /// <param name="Key">密钥</param>
        /// <param name="Vector">向量</param>
        /// <returns>明文</returns>
        public static String AESDecrypt(String Data, String Key, String Vector)
        {
            Byte[] encryptedBytes = Convert.FromBase64String(Data);
            Byte[] original = null; // 解密后的明文
            MemoryStream Memoryx = new MemoryStream(encryptedBytes);
            if (AESDecrypt(ref Memoryx, Key, Vector))
                original = Memoryx.ToArray();
            return Encoding.UTF8.GetString(original);
        }

        /// <summary>
        /// AES加密(无向量)
        /// </summary>
        /// <param name="plainBytes">被加密的明文</param>
        /// <param name="key">密钥</param>
        /// <returns>密文</returns>
        public static string AESEncrypt(String Data, String Key)
        {
            MemoryStream mStream = new MemoryStream();
            RijndaelManaged aes = new RijndaelManaged();
            byte[] plainBytes = Encoding.UTF8.GetBytes(Data);
            Byte[] bKey = new Byte[32];
            Array.Copy(Encoding.UTF8.GetBytes(Key.PadRight(bKey.Length)), bKey, bKey.Length);
            aes.Mode = CipherMode.ECB;
            aes.Padding = PaddingMode.PKCS7;
            aes.KeySize = 128;
            //aes.Key = _key;
            aes.Key = bKey;
            //aes.IV = _iV;
            CryptoStream cryptoStream = new CryptoStream(mStream, aes.CreateEncryptor(), CryptoStreamMode.Write);
            try
            {
                cryptoStream.Write(plainBytes, 0, plainBytes.Length);
                cryptoStream.FlushFinalBlock();
                return Convert.ToBase64String(mStream.ToArray());
            }
            finally
            {
                cryptoStream.Close();
                mStream.Close();
                aes.Clear();
            }
        }

        /// <summary>
        /// AES解密(无向量)
        /// </summary>
        /// <param name="encryptedBytes">被加密的明文</param>
        /// <param name="key">密钥</param>
        /// <returns>明文</returns>
        public static string AESDecrypt(String Data, String Key)
        {
            Byte[] encryptedBytes = Convert.FromBase64String(Data);
            Byte[] bKey = new Byte[32];
            Array.Copy(Encoding.UTF8.GetBytes(Key.PadRight(bKey.Length)), bKey, bKey.Length);
            MemoryStream mStream = new MemoryStream(encryptedBytes);
            //mStream.Write( encryptedBytes, 0, encryptedBytes.Length );
            //mStream.Seek( 0, SeekOrigin.Begin );
            RijndaelManaged aes = new RijndaelManaged();
            aes.Mode = CipherMode.ECB;
            aes.Padding = PaddingMode.PKCS7;
            aes.KeySize = 128;
            aes.Key = bKey;
            //aes.IV = _iV;
            CryptoStream cryptoStream = new CryptoStream(mStream, aes.CreateDecryptor(), CryptoStreamMode.Read);
            try
            {
                byte[] tmp = new byte[encryptedBytes.Length + 32];
                int len = cryptoStream.Read(tmp, 0, encryptedBytes.Length + 32);
                byte[] ret = new byte[len];
                Array.Copy(tmp, 0, ret, 0, len);
                return Encoding.UTF8.GetString(ret);
            }
            finally
            {
                cryptoStream.Close();
                mStream.Close();
                aes.Clear();
            }
        }

        private static string GetAESIV(int ikey)
        {
            string[] fstrlist = new string[256]{
            "DC74FA61BC774E98","7FD074D3595845C9","0795B6E0D96D4852","DF51DFC66A2149C6",
            "27D9D6B3C70F41D3","D6EB4C849EDE4A15","39AB8FCB34F541E1","3C112A1EBF88466E",
            "BCFAE75FA0394294","ED3612D3E5E64AF6","875D47F0BD4B43C5","C201DB4C7D114C5C",
            "B8C78976DBEC4BE2","04FC334852284327","9E131DADFE644E49","FF73F21B812249A2",
            "405FA449C657453A","15867676002C408F","2C7FA57D55E54E88","F8285AD6E75B4358",
            "2E6F3826358B4312","36601B293E9E410A","12F9D1C5EAEC47DA","E09437E4D45B488F",
            "A672D5297A7B44CF","3CA781E6C83A4AB2","CB05F9F3DB9F43C7","3532B46BAE0C4052",
            "C2EF6083779A4821","6507069CE6AA4E36","F2FF1CB66CEA4671","190129CA75124858",
            "1C0F75654BD84D43","C8973A3A65D64EAC","7B764DAF516248F8","3708339DCB024FC3",
            "6BA4C3FDF8124A78","1C80B7589A324166","5BFF60E4859042E1","B6BFA7464EE04028",
            "A5622B14BD364193","0F2F2D7AC6494430","A2A5D53FBD3745F0","AF895DA8D01043F3",
            "32BEB6A50DB440C7","FC012C52D28E4353","8B188AAF12884563","DFC7BF44F15B4F0C",
            "C4312D31B6B84C99","8F8184202064431C","642E12BAD6DC4CF7","B81F832BA4EB4D66",
            "64CAEFFD68284F45","B253C32032624CA8","02E212F0FE4846E9","6CDD3065A02E4175",
            "A86582D3715F443B","DAA153E68F7A4B08","DCCE0B908C6545EF","58AC165252DF457B",
            "B10099E3B8ED43FF","288CFD0AFA104535","74EB01986539422D","95E91752E74643D2",
            "F157EB4838B3420B","88E52B4747F04859","FA37CCF7AEBB4EB5","501C81929D144381",
            "0B8DDF66DF944F00","40848B94940E460A","1C66693CA10A47F2","78990471986849FA",
            "30EB26DED6FA4714","02EEF9438C1A486D","4FE503AE1E7F4E18","C4CA3CEB787E4294",
            "AE1CCC29D42F4974","5445D0E30B944FDE","87ACDB429ED54860","625C94D665D74B7B",
            "DD15A1DF83D1443B","228B952609EF47ED","9BDB56010D214177","02DB2ECA75084F1A",
            "0FD61A605BDF4113","0C4F272FD8D04274","AEA9C2EFCDE140A8","0BB2827EFEDD4D59",
            "44CF4274D90544C2","A67B0A0244684A30","8A23C40554F641F2","2EF33A37FA1B47CE",
            "2A6E62C6E47D42FA","DA829A44E54240B7","62946D6497A04A8E","CD69394978404A6E",
            "75B4BE51CBE848ED","053EFE2FD6EE4843","B71C104F49DE4582","EB625C3FA2DB4AD1",
            "51FC7FD8EA584590","FBDFDF8AFE1E41D0","2A9038F538A145D3","8093606A139F42C6",
            "EE44EF3EE03A4359","58589573662C4B7B","293026EB25F04DF9","62D7A5D3238340C5",
            "C1DC543C778C49EC","0BD11340DDD64073","B914F711E7AC4255","02E999CB63FC481D",
            "3CA1A4AE5F974EA4","06AB7EF69CDE4419","3EC7F923F46C4F39","FA7B4BF4DBD240D5",
            "4332BCFBA53F40E1","8803714F94CF42C6","477C50D267294B73","FD8C07ABEF584458",
            "A4D7FF2669A2453B","41C4BBB8D2194DD7","3D8AAF44688B4359","23EF1A17737D4125",
            "A0DFE9F441274759","F33C2C38AD1F4334","74ECD6A488DA4FE3","2F89880721A64EEE",
            "745215DFB56344E3","763267B8F71B4CA3","C3D64846670A4689","85C4A08B5EC24A58",
            "DC284042FB4A45F4","797ED8D8E8DA4062","8040B997D1F045A7","DB7CED0BA1E24EC5",
            "52E02478DEFC400B","BB42A37F51884E3E","512228053C044EF6","0D18316E2F694774",
            "C46D8825E4154423","263E8DBAD408447A","B91DEBBCBD644524","CCD2AFF63B6C4AFC",
            "CBEB3C0F8009464D","4F0EFF2CB9B84DE9","24E53A274BF74D6C","20AA809288C44394",
            "AC35661B91E44EF8","28AA5BC3C8674CA1","D4596135650B450F","AEBD6895FEB04584",
            "8D8F11609083452B","54C0E2CF57A14042","CD91E168996D4127","CE3E15978616434E",
            "1CA0E5E7EC0C4D0C","BD875423A2854042","C6A91D4564A741F2","A44903AD4C854213",
            "CAD904E8B5D946C2","F4F8C87FC741444A","A254D4801D154EEF","00E056A66D0E424F",
            "203704ACAEA14614","24C32DFC45614C08","C11D7CB92F3B4D69","CDB4BE307C694898",
            "19F02D74A8D1494F","200CD63DD4604D1A","0A91FD285B3C41A8","B9CBCEDC89CE4F7F",
            "5F043EF781034BFB","243260922C404BC2","60B05986122F491C","23F257B38C5440B8",
            "D82075CCCF6E49FC","742BA2C352314249","DC4D377A5C524915","D98E99C2F1974673",
            "CDB6B1CCDB314367","7B02B7D782224614","A879EF99D4B94E6A","6E643A3AF0574E53",
            "82E2141DBD76425E","43601DDAFD5A408D","67B8AADF2C394367","B0903C8DB7DF4FF0",
            "57580DF94942471E","01FDD12B98CB4B23","8EA278DBF2E74EEA","8829B0BDC5D54176",
            "FCFCCB8B391A4250","34B71D3F797943B1","C776111E26C1469F","9B50DC4676444B9F",
            "C7B34832F9D94642","333ABC1344D648EA","3472866F73884D3E","D339D1623AAD4174",
            "94DA91C716F54B2B","59BC1D20719C4D78","4CA8141D9F554742","48580FEC4F4B43A0",
            "5375B4D38958462B","2D00C2B16F334D29","72440AEC06BD473D","D68D610D4B154206",
            "E3FA8361F367409C","24AD55C3455647AE","7B5BBD1DFCE944E4","B25438443FBE4E3D",
            "0D493DDA80334123","5FD4E9E843D049EA","2C3002915B2C4C10","68E1790986494A18",
            "4ACA0482C7BB40A0","A3AD2B4CB9C14513","77FEFD673414400A","843DE4D161A546CD",
            "366788C62F42444C","7D64A50ABF7349FB","D7F4244F09FA4053","0A76A3FA1FF7419E",
            "52111AE6761D4354","486058BF8D6547BA","9CDA8B6BE57647C6","4DF154FA13E34599",
            "F6168996A5454CFF","0792670B4A8C4A79","05991826436B4B2D","F2DEE401075D48BC",
            "911322B7E99F47AF","49FD50C107DD4A47","32EE5216BDE04D94","8DD72F2AD34D4E9D",
            "C4843F1468324F9C","9A5B26B4E51A40FA","5217163BE5474370","BBDB079B09A847A9",
            "CD77D2B63F1446AF","42BF6414364748F9","09ED02163B6E4142","22D9067D898A420C",
            "B996FE0CDF234AA2","D816F70F40E34865","B8740703AC78447C","3660D36FBE9747D1",
            "B0F1CE5CC00149B6","EB4D7D059BE04F87","29B8BDF094FD48DE","0C14D41DA1E94734",
            "24C11304BDB74D50","94797C7098DD4AB9","D6D66F9963764576","C758B5AB4B9D4C5D",
            };
            return fstrlist[ikey % 256];
        }

        public static string AESSelfDecrypt(String Data)
        {
            string fstr = Data.Substring(0, 2);
            byte[] btemp = Convert.FromBase64String(fstr + "==");
            return AESDecrypt(Data.Substring(2), GetAESIV(btemp[0]));
        }

        public static string AESSelfEncrypt(String Data)
        {
            Random frd = new Random();
            byte ikey = (byte)frd.Next(0, 0xFF);
            string fstr = Convert.ToBase64String(new byte[] { ikey }).Substring(0, 2);
            return fstr + AESEncrypt(Data, GetAESIV(ikey));
        }
    }
}
